가상 면접 사례로 배우는 생성형 AI 시스템 설계 — 0장 선수지식 딥다이브 학습 노트

출처: 가상 면접 사례로 배우는 생성형 AI 시스템 설계 (알리 아미니안, 알렉스 쉬) | 참고: https://www.aliaminian.com/books


전체 흐름도

┌──────────────────────────────────────────────────────────────┐
│                    선수지식 → 생성형 AI 연결 맵                  │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  [0.1 확률/통계]                                              │
│   └─ 조건부확률, 베이즈 → P(Y|X) 판별형, P(X) 생성형           │
│                                                              │
│  [0.2 선형대수]                                               │
│   └─ 행렬 곱, 내적 → 어텐션 Q·K^T, 가중치 행렬 W              │
│                                                              │
│  [0.3 머신러닝 기초]                                           │
│   └─ 지도/비지도/자기지도 → 사전학습, 미세조정 이해             │
│                                                              │
│  [0.4 Python/numpy]                                          │
│   └─ 배열 연산, 브로드캐스팅 → 모든 코드 예제의 기반           │
│                                                              │
│  [0.5 딥러닝 기초]                                            │
│   └─ 신경망, 역전파, 활성화 → 트랜스포머, GAN, 확산 모델       │
│                                                              │
└──────────────────────────────────────────────────────────────┘

선수 지식 체크리스트

  • [ ] 확률의 기본 (사건, 조건부 확률, 독립)
  • [ ] 베이즈 정리 (사전확률, 우도, 사후확률)
  • [ ] 벡터와 행렬 연산 (덧셈, 곱셈, 전치, 내적)
  • [ ] softmax 함수의 의미와 계산
  • [ ] 지도학습, 비지도학습, 자기 지도 학습 구분
  • [ ] numpy 기본 (배열 생성, 인덱싱, 연산)
  • [ ] 신경망 기본 구조 (입력층, 은닉층, 출력층)
  • [ ] 활성화 함수 (Sigmoid, ReLU)
  • [ ] 역전파와 경사 하강법 원리

핵심 키워드

용어 의미
확률 (Probability) 어떤 사건이 일어날 가능성을 0~1 사이 숫자로 표현
조건부 확률 P(A|B) B가 일어났다는 조건 하에 A가 일어날 확률
베이즈 정리 새로운 증거를 바탕으로 사전 확률을 업데이트하는 공식
정규 분포 종 모양의 대칭 확률 분포. 자연현상에서 가장 흔함
벡터 (Vector) 크기와 방향을 가진 양. 1차원 배열로 표현
행렬 (Matrix) 숫자를 2차원으로 배열한 것. 데이터 변환에 사용
내적 (Dot Product) 두 벡터의 원소별 곱의 합. 유사도 측정에 사용
전치 (Transpose) 행과 열을 뒤바꾸는 연산
softmax 실수 벡터를 확률 분포(합=1)로 변환하는 함수
지도 학습 정답(레이블)이 있는 데이터로 학습
비지도 학습 정답 없이 데이터의 패턴을 스스로 발견
자기 지도 학습 데이터 자체에서 학습 신호를 만들어 학습 (예: 빈칸 채우기)
과적합 (Overfitting) 학습 데이터에는 잘 맞지만 새 데이터에는 못 맞는 상태
뉴런 (Neuron) 신경망의 기본 단위. 입력의 가중합 + 활성화 함수
활성화 함수 뉴런의 출력을 비선형으로 변환 (Sigmoid, ReLU 등)
역전파 (Backpropagation) 출력의 오차를 역방향으로 전파하여 가중치를 업데이트
경사 하강법 (Gradient Descent) 손실 함수의 기울기 방향으로 매개변수를 조금씩 조정
손실 함수 (Loss Function) 모델 예측과 실제 값의 차이를 측정하는 함수
학습률 (Learning Rate) 한 번의 업데이트에서 매개변수를 얼마나 바꿀지 결정하는 값
에포크 (Epoch) 전체 학습 데이터를 한 번 다 사용하는 학습 주기

0.1 확률과 통계 기초

한 줄 요약

확률은 "불확실한 것을 숫자로 표현"하는 도구이며, 베이즈 정리는 "새 증거를 보고 생각을 업데이트"하는 방법이다.

쉬운 설명 (비유로 풀어쓰기)

확률 = 날씨 예보 - "내일 비 올 확률 70%" → 완전히 확실하지 않지만 숫자로 표현 - 0 = 절대 안 일어남, 1 = 반드시 일어남

조건부 확률 = "우산을 가져간 사람 중에서 비를 맞은 사람의 비율" - P(비|우산) = "우산을 가져갔는데 비가 올 확률" - P(우산|비) = "비가 오는데 우산을 가져온 확률" (다른 값!)

베이즈 정리 = 의사의 진단 업데이트 - 처음 생각: "이 질병은 1000명 중 1명" (사전 확률) - 검사 양성 나옴 → "그래도 실제 확률은 9% 정도" (사후 확률) - 왜? 검사가 100% 정확하지 않으니까 (위양성 존재)

실무 예제

import numpy as np

# === 1. 동전 던지기 시뮬레이션 ===
np.random.seed(42)
flips = np.random.choice(["앞", "뒤"], size=10000)
head_ratio = np.sum(flips == "앞") / len(flips)
print(f"동전 10000번: 앞면 비율 = {head_ratio:.4f} (이론: 0.5)")

# === 2. 조건부 확률: 스팸 필터 ===
total = 1000
spam = 200
has_free = 150
spam_and_free = 120

# P(스팸 | "무료" 포함)
p_spam_given_free = spam_and_free / has_free
print(f"\nP(스팸 | '무료' 포함) = {p_spam_given_free:.2f}")  # 0.80

# P("무료" 포함 | 스팸)
p_free_given_spam = spam_and_free / spam
print(f"P('무료' 포함 | 스팸) = {p_free_given_spam:.2f}")    # 0.60
# → 두 값이 다르다! 조건부 확률의 방향이 중요

# === 3. 베이즈 정리: 질병 검사 ===
# 질병 유병률 0.1% (1000명 중 1명)
p_disease = 0.001
# 검사 민감도 99% (질병 있으면 양성 나올 확률)
p_positive_given_disease = 0.99
# 위양성률 5% (질병 없는데 양성 나올 확률)
p_positive_given_no_disease = 0.05

# 베이즈 정리로 P(질병 | 양성) 계산
p_positive = (p_positive_given_disease * p_disease +
              p_positive_given_no_disease * (1 - p_disease))
p_disease_given_positive = (p_positive_given_disease * p_disease) / p_positive

print(f"\n[베이즈 정리] 검사 양성일 때 실제 질병 확률: {p_disease_given_positive:.4f}")
print(f"→ 약 {p_disease_given_positive*100:.1f}%  (99%가 아니라 ~2%!)")

# === 4. 정규 분포 ===
# 평균=0, 표준편차=1인 정규분포에서 1000개 샘플
samples = np.random.normal(loc=0, scale=1, size=1000)
print(f"\n정규분포 샘플 1000개: 평균={np.mean(samples):.3f}, 표준편차={np.std(samples):.3f}")

# === 5. 기대값과 분산 ===
# 주사위의 기대값
die = np.array([1, 2, 3, 4, 5, 6])
probs = np.ones(6) / 6  # 각 1/6
expected = np.sum(die * probs)
variance = np.sum((die - expected)**2 * probs)
print(f"\n주사위 기대값: {expected:.2f} (이론: 3.5)")
print(f"주사위 분산: {variance:.2f} (이론: 2.917)")

핵심 체크포인트

  • ✅ 조건부 확률 P(A|B) ≠ P(B|A) — 방향이 다르면 값도 다르다
  • ✅ 베이즈 정리: P(A|B) = P(B|A)·P(A) / P(B) — 새 증거로 믿음을 업데이트
  • ✅ 생성형 AI에서 확률은 "다음 토큰이 나올 가능성"을 계산하는 핵심

0.2 선형대수 기초

한 줄 요약

벡터는 "방향이 있는 숫자 목록", 행렬은 "변환 도구"이며, 이 둘의 곱셈이 신경망의 핵심 연산이다.

쉬운 설명 (비유로 풀어쓰기)

벡터 = 쇼핑 목록 - [사과 3개, 바나나 2개, 우유 1개] → 3차원 벡터 [3, 2, 1] - 각 숫자가 하나의 "특성"을 나타냄

행렬 = 변환 레시피 - "이 재료들로 케이크를 만들려면..." → 재료(벡터)에 레시피(행렬)를 적용하면 결과물(새 벡터) - 신경망에서 가중치 행렬 W가 바로 이 "변환 레시피"

내적(Dot Product) = 두 사람의 취향 비교 - A가 좋아하는 것 [영화 5점, 음악 3점, 운동 1점] - B가 좋아하는 것 [영화 4점, 음악 1점, 운동 5점] - 내적 = 5×4 + 3×1 + 1×5 = 28 → 숫자가 클수록 취향이 비슷! - 어텐션에서 Q·K가 바로 이 내적 → "이 단어들이 얼마나 관련있는지" 점수

실무 예제

import numpy as np

# === 1. 벡터 기본 ===
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

print("=== 벡터 연산 ===")
print(f"a = {a}")
print(f"b = {b}")
print(f"a + b = {a + b}")          # [5, 7, 9]
print(f"a * 3 = {a * 3}")          # [3, 6, 9] 스칼라 곱
print(f"a * b = {a * b}")          # [4, 10, 18] 원소별 곱
print(f"내적 a·b = {np.dot(a, b)}")  # 32

# === 2. 행렬 기본 ===
W = np.array([[1, 2],
              [3, 4],
              [5, 6]])  # 3×2 행렬

x = np.array([10, 20])   # 2차원 입력 벡터

print("\n=== 행렬 × 벡터 ===")
print(f"W (3×2):\n{W}")
print(f"x (2,): {x}")
print(f"W @ x = {W @ x}")  # [50, 110, 170] → 3차원 출력!
# 핵심: 2차원 → 3차원으로 "변환"

# === 3. 전치 ===
print(f"\n=== 전치 ===")
print(f"W:\n{W}")
print(f"W.T:\n{W.T}")  # 3×2 → 2×3

# === 4. 행렬 곱 ===
A = np.array([[1, 2], [3, 4]])  # 2×2
B = np.array([[5, 6], [7, 8]])  # 2×2
print(f"\n=== 행렬 곱 ===")
print(f"A @ B =\n{A @ B}")
print(f"B @ A =\n{B @ A}")
print("→ A@B ≠ B@A! 행렬 곱은 교환법칙이 성립하지 않음")

# === 5. softmax — 생성형 AI의 핵심 함수 ===
def softmax(x):
    """실수 벡터를 확률 분포로 변환"""
    exp_x = np.exp(x - np.max(x))  # 수치 안정성
    return exp_x / exp_x.sum()

logits = np.array([2.0, 1.0, 0.1])  # 모델의 원시 출력
probs = softmax(logits)

print(f"\n=== softmax ===")
print(f"입력 (logits): {logits}")
print(f"출력 (확률):   {probs}")
print(f"합계: {probs.sum():.4f}")  # 1.0000
print("→ 가장 큰 값(2.0)이 가장 높은 확률(0.659)로 변환됨")

# === 6. 내적 → 어텐션 점수 미리보기 ===
# "나는 은행에서 돈을 찾았다"
q_bank = np.array([0.8, 0.1])   # "은행"의 쿼리 벡터
k_money = np.array([0.9, 0.2])  # "돈"의 키 벡터
k_sat = np.array([0.1, 0.7])    # "앉았다"의 키 벡터

score_money = np.dot(q_bank, k_money)
score_sat = np.dot(q_bank, k_sat)
print(f"\n=== 어텐션 점수 미리보기 ===")
print(f"'은행'과 '돈'의 관련도:     {score_money:.2f}")
print(f"'은행'과 '앉았다'의 관련도: {score_sat:.2f}")
print(f"→ '돈'과 더 관련 높음 → 금융기관으로 해석")

핵심 체크포인트

  • ✅ 행렬 곱 (W @ x): 벡터를 다른 차원으로 변환 — 신경망의 기본 연산
  • ✅ 내적 (dot product): 두 벡터의 유사도 — 어텐션의 Q·K 계산에 사용
  • ✅ softmax: 숫자 → 확률 분포(합=1) — 다음 토큰 확률, 어텐션 가중치에 사용
  • ✅ 행렬 곱은 교환법칙 안 됨: A@B ≠ B@A

0.3 머신러닝 기초

한 줄 요약

머신러닝은 "데이터에서 규칙을 스스로 학습"하는 것이며, 생성형 AI의 자기 지도 학습은 "레이블 없이도 학습할 수 있는" 혁신이다.

쉬운 설명 (비유로 풀어쓰기)

규칙 기반 vs 머신러닝 = 요리 - 규칙 기반: "소금 5g, 후추 3g, 180도 20분" → 레시피대로만 - 머신러닝: 100개 요리를 먹어보고 → "이런 조합이 맛있구나" 스스로 깨달음

지도 학습 = 선생님이 정답을 알려주는 시험 공부 - "이 이메일은 스팸이야" (정답 제공) → 패턴 학습 → 새 이메일 분류

비지도 학습 = 정답 없이 스스로 분류 - 동물원에서 동물들을 보고 "얘네는 비슷하게 생겼네" → 그룹핑

자기 지도 학습 = 빈칸 채우기 퀴즈 - "나는 오늘 ___에서 밥을 먹었다" → "식당"을 맞추면서 언어를 배움 - GPT가 바로 이 방식! 인터넷 텍스트에서 다음 단어를 예측하며 학습

실무 예제

import numpy as np

# === 1. 선형 회귀: 경사 하강법으로 처음부터 구현 ===
# y = 3x + 2 를 학습해보자
np.random.seed(42)

# 학습 데이터 생성
X = np.random.uniform(0, 10, 50)
y = 3 * X + 2 + np.random.normal(0, 1, 50)  # 약간의 노이즈

# 매개변수 초기화
w = 0.0  # 가중치 (기울기)
b = 0.0  # 편향 (절편)
lr = 0.001  # 학습률

print("=== 경사 하강법으로 선형 회귀 학습 ===")
for epoch in range(100):
    # 예측
    y_pred = w * X + b

    # 손실 (MSE)
    loss = np.mean((y - y_pred) ** 2)

    # 기울기 계산
    dw = -2 * np.mean(X * (y - y_pred))
    db = -2 * np.mean(y - y_pred)

    # 매개변수 업데이트
    w -= lr * dw
    b -= lr * db

    if epoch % 20 == 0:
        print(f"  에포크 {epoch:3d}: 손실={loss:.4f}, w={w:.4f}, b={b:.4f}")

print(f"\n  최종: w={w:.4f} (정답: 3.0), b={b:.4f} (정답: 2.0)")

# === 2. 과적합 시연 ===
# 데이터: 5개 점
x_train = np.array([1, 2, 3, 4, 5], dtype=float)
y_train = np.array([2.1, 4.0, 5.8, 8.1, 9.9])

# 1차 (적절): y = ax + b
coeffs_1 = np.polyfit(x_train, y_train, 1)
# 4차 (과적합): 데이터 5개에 매개변수 5개
coeffs_4 = np.polyfit(x_train, y_train, 4)

# 새 데이터에서 비교
x_test = np.array([2.5, 3.5])
y_test = np.array([5.0, 7.0])  # 실제 값

pred_1 = np.polyval(coeffs_1, x_test)
pred_4 = np.polyval(coeffs_4, x_test)

print("\n=== 과적합 vs 적절한 모델 ===")
print(f"  1차 모델 예측: {pred_1} (실제: {y_test})")
print(f"  4차 모델 예측: {pred_4} (실제: {y_test})")
print(f"  1차 오차: {np.mean(np.abs(pred_1 - y_test)):.4f}")
print(f"  4차 오차: {np.mean(np.abs(pred_4 - y_test)):.4f}")
print("→ 4차 모델은 학습 데이터에 완벽히 맞지만 새 데이터에서 오차가 클 수 있음")

# === 3. 자기 지도 학습 시뮬레이션 ===
sentence = "나는 오늘 학교에서 수학을 공부했다"
words = sentence.split()
print(f"\n=== 자기 지도 학습 (다음 단어 예측) ===")
for i in range(len(words) - 1):
    context = " ".join(words[:i+1])
    target = words[i+1]
    print(f"  입력: '{context}' → 예측 대상: '{target}'")
print("→ 레이블 없이 텍스트 자체에서 학습 신호를 만듦!")

핵심 체크포인트

  • ✅ 경사 하강법: 기울기 방향의 반대로 매개변수를 조금씩 업데이트
  • ✅ 과적합: 매개변수가 데이터보다 많으면 위험 → 검증 데이터로 확인
  • ✅ 자기 지도 학습: 레이블 없이 데이터 자체에서 학습 → 생성형 AI의 핵심 원동력

0.4 Python/numpy 기초

한 줄 요약

numpy는 "빠른 숫자 배열 연산 도구"이며, ML/딥러닝 코드의 거의 모든 연산이 numpy 위에서 동작한다.

쉬운 설명 (비유로 풀어쓰기)

Python 리스트 = 한 줄로 선 사람들 (하나씩 처리) numpy 배열 = 군대 대형 (한 번에 전체 이동)

for문으로 100만 개를 하나씩 더하면 느리지만, numpy는 내부적으로 C언어로 한 번에 처리!

실무 예제

import numpy as np

# === 1. 배열 생성 ===
print("=== 배열 생성 ===")
a = np.array([1, 2, 3, 4, 5])
print(f"np.array: {a}")
print(f"np.zeros(3): {np.zeros(3)}")
print(f"np.ones((2,3)):\n{np.ones((2,3))}")
print(f"np.arange(0, 10, 2): {np.arange(0, 10, 2)}")
print(f"np.linspace(0, 1, 5): {np.linspace(0, 1, 5)}")

# === 2. 인덱싱과 슬라이싱 ===
print("\n=== 인덱싱 ===")
m = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])
print(f"행렬:\n{m}")
print(f"m[0, 1] = {m[0, 1]}")       # 2
print(f"m[:, 0] = {m[:, 0]}")       # 1열: [1, 4, 7]
print(f"m[1:, :2] =\n{m[1:, :2]}")  # 2~3행, 1~2열

# === 3. 연산 ===
print("\n=== 배열 연산 ===")
x = np.array([1, 2, 3, 4])
print(f"x = {x}")
print(f"x + 10 = {x + 10}")         # 브로드캐스팅
print(f"x ** 2 = {x ** 2}")         # 원소별 제곱
print(f"np.sum(x) = {np.sum(x)}")
print(f"np.mean(x) = {np.mean(x)}")
print(f"np.max(x) = {np.max(x)}")
print(f"np.argmax(x) = {np.argmax(x)}")  # 최대값의 인덱스

# === 4. 브로드캐스팅 ===
print("\n=== 브로드캐스팅 ===")
A = np.array([[1, 2, 3],
              [4, 5, 6]])  # 2×3
b = np.array([10, 20, 30])  # 1×3

print(f"A (2×3):\n{A}")
print(f"b (3,): {b}")
print(f"A + b =\n{A + b}")  # b가 자동으로 2×3으로 확장!

# === 5. reshape ===
print("\n=== reshape ===")
flat = np.arange(12)
print(f"1D: {flat}")
print(f"reshape(3,4):\n{flat.reshape(3, 4)}")
print(f"reshape(2,2,3):\n{flat.reshape(2, 2, 3)}")

# === 6. 랜덤 ===
print("\n=== 랜덤 ===")
np.random.seed(42)  # 재현 가능한 결과
print(f"randn(5): {np.random.randn(5)}")
print(f"randint(1, 7, 10): {np.random.randint(1, 7, 10)}")  # 주사위 10번

# === 7. ML 실전 패턴 ===
print("\n=== ML 실전 패턴 ===")

# one-hot 인코딩
labels = np.array([0, 2, 1, 0, 2])
n_classes = 3
one_hot = np.eye(n_classes)[labels]
print(f"labels: {labels}")
print(f"one-hot:\n{one_hot}")

# 정규화 (0~1 스케일링)
data = np.array([100, 200, 300, 400, 500])
normalized = (data - data.min()) / (data.max() - data.min())
print(f"\n원본: {data}")
print(f"정규화: {normalized}")

# argmax로 예측 클래스 결정
probs = np.array([[0.1, 0.7, 0.2],
                  [0.8, 0.1, 0.1]])
predictions = np.argmax(probs, axis=1)
print(f"\n확률: {probs}")
print(f"예측 클래스: {predictions}")  # [1, 0]

핵심 체크포인트

  • ✅ numpy 배열은 같은 타입의 데이터만 → 빠른 연산 가능
  • ✅ 브로드캐스팅: 크기가 다른 배열도 자동으로 맞춰서 연산
  • ✅ ML 필수 패턴: one-hot 인코딩, 정규화, argmax → 거의 모든 모델에서 사용

0.5 딥러닝 기초

한 줄 요약

신경망은 "행렬 곱 + 활성화 함수"를 반복 쌓은 것이며, 역전파로 가중치를 업데이트하여 학습한다.

쉬운 설명 (비유로 풀어쓰기)

신경망 = 여러 단계의 필터 체인 - 입력 사진 → [필터1: 윤곽 추출] → [필터2: 패턴 인식] → [필터3: 분류] → "고양이" - 각 필터 = 하나의 층(layer), 필터의 설정값 = 가중치(weight)

활성화 함수 = 문턱 - 입력이 일정 수준을 넘으면 "발동!" (비선형성 추가) - 없으면 아무리 층을 쌓아도 결국 하나의 행렬 곱과 같음

역전파 = 시험 채점 후 복습 1. 순전파: 시험 봄 (예측) 2. 채점: 틀린 문제 확인 (손실 계산) 3. 역전파: 어디서 틀렸는지 역추적 (기울기 계산) 4. 복습: 약한 부분 강화 (가중치 업데이트)

실무 예제

import numpy as np

# === 1. 활성화 함수 비교 ===
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def relu(x):
    return np.maximum(0, x)

def tanh(x):
    return np.tanh(x)

x = np.array([-3, -1, 0, 1, 3])
print("=== 활성화 함수 비교 ===")
print(f"입력:    {x}")
print(f"Sigmoid: {sigmoid(x)}")
print(f"ReLU:    {relu(x)}")
print(f"Tanh:    {tanh(x)}")
print("→ Sigmoid: 0~1 출력 (확률), ReLU: 0 이하 차단 (가장 인기), Tanh: -1~1")

# === 2. 퍼셉트론으로 AND 게이트 ===
print("\n=== 퍼셉트론: AND 게이트 ===")
# AND: 둘 다 1일 때만 1
w = np.array([0.5, 0.5])
b = -0.7

for x1, x2 in [(0,0), (0,1), (1,0), (1,1)]:
    x = np.array([x1, x2])
    output = 1 if np.dot(w, x) + b > 0 else 0
    print(f"  AND({x1}, {x2}) = {output}")

# === 3. 2층 신경망으로 XOR 풀기 (핵심 예제!) ===
print("\n=== 2층 신경망: XOR 학습 ===")
# XOR: 같으면 0, 다르면 1
X = np.array([[0,0], [0,1], [1,0], [1,1]])
y = np.array([[0], [1], [1], [0]])

np.random.seed(42)
# 가중치 초기화
W1 = np.random.randn(2, 4) * 0.5   # 입력(2) → 은닉(4)
b1 = np.zeros((1, 4))
W2 = np.random.randn(4, 1) * 0.5   # 은닉(4) → 출력(1)
b2 = np.zeros((1, 1))

lr = 0.5

for epoch in range(5000):
    # --- 순전파 ---
    z1 = X @ W1 + b1           # 은닉층 입력
    a1 = sigmoid(z1)           # 은닉층 출력 (활성화)
    z2 = a1 @ W2 + b2          # 출력층 입력
    a2 = sigmoid(z2)           # 최종 출력

    # --- 손실 (MSE) ---
    loss = np.mean((y - a2) ** 2)

    # --- 역전파 ---
    # 출력층
    d2 = (a2 - y) * a2 * (1 - a2)  # sigmoid 미분
    dW2 = a1.T @ d2
    db2 = np.sum(d2, axis=0, keepdims=True)

    # 은닉층
    d1 = (d2 @ W2.T) * a1 * (1 - a1)
    dW1 = X.T @ d1
    db1 = np.sum(d1, axis=0, keepdims=True)

    # --- 업데이트 ---
    W2 -= lr * dW2
    b2 -= lr * db2
    W1 -= lr * dW1
    b1 -= lr * db1

    if epoch % 1000 == 0:
        print(f"  에포크 {epoch}: 손실 = {loss:.6f}")

# 최종 결과
print(f"\n  최종 예측:")
for i in range(4):
    pred = a2[i, 0]
    print(f"    XOR({X[i,0]}, {X[i,1]}) = {pred:.4f} (목표: {y[i,0]})")

# === 4. 손실 함수 비교 ===
print("\n=== 손실 함수 ===")
y_true = np.array([1, 0, 1, 1])
y_pred = np.array([0.9, 0.1, 0.8, 0.6])

# MSE (평균 제곱 오차) — 회귀에서 주로 사용
mse = np.mean((y_true - y_pred) ** 2)
print(f"  MSE: {mse:.4f}")

# Cross-Entropy — 분류에서 주로 사용
eps = 1e-15  # log(0) 방지
ce = -np.mean(y_true * np.log(y_pred + eps) + (1-y_true) * np.log(1-y_pred + eps))
print(f"  Cross-Entropy: {ce:.4f}")
print("→ 분류 문제에서는 Cross-Entropy가 더 효과적 (기울기가 더 잘 전달됨)")

핵심 체크포인트

  • ✅ 신경망 = 행렬 곱(W @ x + b) + 활성화 함수를 반복 쌓은 것
  • ✅ 활성화 함수 없이는 깊이를 쌓아도 의미 없음 (비선형성이 필수)
  • ✅ 역전파: 출력 오차 → 각 가중치가 오차에 기여한 정도 계산 → 업데이트
  • ✅ XOR 문제: 단층 퍼셉트론으로 불가능 → 은닉층 추가로 해결 (딥러닝의 핵심!)

연습문제

연습문제 1: 베이즈 정리 응용

문제: 어떤 공장에서 불량품 비율이 2%이다. 검사기의 불량 탐지율은 95%, 오탐률은 3%이다. 검사기가 "불량"이라고 판정했을 때 실제 불량일 확률을 구하시오.

풀이:

P(불량) = 0.02
P(양성|불량) = 0.95
P(양성|정상) = 0.03

P(양성) = 0.95 × 0.02 + 0.03 × 0.98 = 0.019 + 0.0294 = 0.0484
P(불량|양성) = (0.95 × 0.02) / 0.0484 = 0.019 / 0.0484 ≈ 0.3926

답: 약 39.3% — 검사기가 불량이라고 해도 실제 불량일 확률은 39%밖에 안 됨!

연습문제 2: softmax 직접 계산

문제: 입력 벡터 [3.0, 1.0, -1.0]에 대해 softmax를 수동으로 계산하시오.

풀이:

exp(3.0) = 20.09, exp(1.0) = 2.72, exp(-1.0) = 0.37
합계 = 23.18
softmax = [20.09/23.18, 2.72/23.18, 0.37/23.18] = [0.867, 0.117, 0.016]
→ 가장 큰 값이 86.7%의 확률로 변환됨

연습문제 3: XOR 신경망 분석

문제: 위 XOR 예제에서 은닉층 뉴런을 2개로 줄이면 어떻게 되는가? 학습이 가능한지 실험하고 이유를 설명하시오.

풀이: W1을 (2, 2)로 바꾸고 실행하면 학습이 불안정하거나 실패할 수 있다. XOR은 최소 2개의 은닉 뉴런이 필요하지만, 초기값에 따라 수렴이 어려울 수 있다. 4개로 늘리면 여유가 생겨 안정적으로 학습된다. 이것이 "모델 역량(capacity)"의 개념이다.


부록 A: 용어 사전

한글 영문 의미
확률 Probability 사건이 일어날 가능성 (0~1)
조건부 확률 Conditional Probability 조건 하의 확률 P(A|B)
베이즈 정리 Bayes' Theorem 사후확률 = 우도 × 사전확률 / 증거
벡터 Vector 크기와 방향을 가진 1차원 배열
행렬 Matrix 2차원 숫자 배열
내적 Dot Product 벡터 유사도 계산
softmax Softmax 실수 → 확률 분포 변환
경사 하강법 Gradient Descent 기울기 반대 방향으로 매개변수 업데이트
역전파 Backpropagation 오차를 역방향 전파하여 기울기 계산
활성화 함수 Activation Function 비선형 변환 (Sigmoid, ReLU 등)
과적합 Overfitting 학습 데이터에만 맞고 일반화 실패

부록 B: 핵심 비교표

학습 방식 비교

방식 정답 필요? 핵심 아이디어 예시
지도 학습 필요 정답 보고 배움 이메일 스팸 분류
비지도 학습 불필요 패턴 스스로 발견 고객 세그먼테이션
자기 지도 학습 불필요 데이터 자체에서 학습 GPT 다음 단어 예측

활성화 함수 비교

함수 출력 범위 장점 단점
Sigmoid 0~1 확률 해석 가능 기울기 소실 문제
ReLU 0~∞ 계산 빠름, 기울기 소실 없음 음수 입력 시 죽은 뉴런
Tanh -1~1 0 중심 출력 기울기 소실 문제

부록 C: 추천 참고 자료 & 링크

주제 자료 링크
numpy NumPy 공식 튜토리얼 https://numpy.org/doc/stable/user/quickstart.html
선형대수 3Blue1Brown (시각적 설명) https://www.3blue1brown.com/topics/linear-algebra
확률/통계 Khan Academy https://www.khanacademy.org/math/statistics-probability
딥러닝 Deep Learning Book (Goodfellow) https://www.deeplearningbook.org/
PyTorch PyTorch 공식 튜토리얼 https://pytorch.org/tutorials/
신경망 Neural Networks and Deep Learning (Michael Nielsen) http://neuralnetworksanddeeplearning.com/
난이도
에피소드
질문
카드를 로딩 중...
답변

클릭하거나 Space를 눌러 뒤집기

0 / 0
학습 진도 0%
이동   Space 뒤집기   R 셔플